﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeDeccodeStr
{
	class Program
	{
		// Класс формирующий алфавит шифрования
		// Алфавит включает в себя eng, ENG, rus, RUS, Digit, Delimiters
		static class ABC
		{
			static StringBuilder sbABC;

			// Статический крнструктор
			static ABC()
			{
				sbABC = new StringBuilder();
			}

			// Свойство возвращает сформированный алфавит
			public static StringBuilder FullABC
			{
				get
				{
					for (char ch = 'a'; ch <= 'z'; ch++)
						sbABC.Append(ch);

					for (char ch = 'A'; ch <= 'Z'; ch++)
						sbABC.Append(ch);

					for (char ch = 'а'; ch <= 'я'; ch++)
						sbABC.Append(ch);

					for (char ch = 'А'; ch <= 'Я'; ch++)
						sbABC.Append(ch);
					// отдельно добавим ё и Ё
					sbABC.Append('ё');
					sbABC.Append('Ё');

					for (char ch = '0'; ch <= '1'; ch++)
						sbABC.Append(ch);

					for (char ch = ' '; ch <= '/'; ch++)
						sbABC.Append(ch);

					for (char ch = ':'; ch <= '?'; ch++)
						sbABC.Append(ch);

					return sbABC;
				}
			}
		}

		static void Main(string[] args)
		{
			// зададим величину смещения
			const int ShiftValue = 5;

			// Создадим алфавит
			StringBuilder myABC = ABC.FullABC;
			// Создадим словарь для шифрации исходной строки
			Dictionary<char, char> DicABC = new Dictionary<char, char>();

			// Заполним словарь, где ключ - это алфавит, значение - это смещение алфавита на ShiftValue вправо
			for (int i = 0; i < myABC.Length; i++)
			{
				// Если выходим за длина афавита - берём символы с начала алфавита
				if (i >= (myABC.Length - ShiftValue))
					DicABC.Add(myABC[i], myABC[i + ShiftValue - myABC.Length]);
				else
					DicABC.Add(myABC[i], myABC[i + ShiftValue]);
			}

			Console.WriteLine("Введите строку для шифрования:");

			// Исходная строка
			StringBuilder SourceStr = new StringBuilder(Console.ReadLine());
			// Кодированная строка
			StringBuilder DestStr = new StringBuilder();

			// Кодируем исходную строку
			for (int i = 0; i < SourceStr.Length; i++)
			{
				// Если найден ключ, добавим значение в DestStr
				if (DicABC.ContainsKey(SourceStr[i]))
				{
					DestStr.Append(DicABC[SourceStr[i]]);
				}
			}
			Console.WriteLine("Закодированная строка:");
			Console.WriteLine(DestStr.ToString());

			// Раскодируем строку
			for (int i = 0; i < DestStr.Length; i++)
			{
				// Если найдено значение в словаре
				if (DicABC.ContainsValue(DestStr[i]))
				{
					// пробежимся по словарю и найдём ключ
					char key = DicABC.FirstOrDefault(x => x.Value == DestStr[i]).Key;
					// Заменим в DestStr значение на ключ из словаря
					DestStr[i] = key;
				}
			}
			Console.WriteLine("Раскодированная строка:");
			Console.WriteLine(DestStr.ToString());
			Console.ReadKey(true);
		}
	}
}
